Categories
React Tips

React Tips — Disabling Links, Portals, and Pass Props to Components Passed in as Props

Spread the love

React is a popular library for creating web apps and mobile apps.

In this article, we’ll look at some tips for writing better React apps.

How to Disable an <Link> if it’s Active

We can disable a link by setting the pointer-events attribute in our CSS.

Since we can pass a className attribute with the CSS class to the Link , we can write:

class Foo extends React.Component {
  render() {
    return (
      <Link to='/bar' className='disabled-link'>click me</Link>
    );
  }
}

We have the disabled-link class name applied to the link.

Then we can add the following CSS to disable the link:

.disabled-link {
  pointer-events: none;
}

How to Use ReactDOM.createPortal()

We can use the ReactDOM.createPortal() to render a component in an element outside of the usual location in the DOM tree,

For instance, given the following HTML:

<html>
  <body>
    <div id="root"></div>
    <div id="portal"></div>
  </body>
</html>

We can write:

const mainContainer = document.getElementById('root');
const portalContainer = document.getElementById('portal');

class Foo extends React.Component {
  render() {
     return (
       <h1>I am rendered through a Portal.</h1>
     );
  }
}

class App extends React.Component {
  render() {
    return (
      <div>
         <h1>Hello World</h1>
         {ReactDOM.createPortal(<Foo />, portalContainer)}
     </div>
    );
  }
}

ReactDOM.render(<App/>, mainContainer);

In App , we called ReactDOM.createPortal(<Foo />, portal to render the Foo component in the portalContainer , which is the div with ID portal in the HTML.

The rest of the JSX code is rendered in their usual places.

This lets us render our components in whatever way we like.

Event Bubbling Through Nested Components in React

React supports synthetic events in both the capturing and bubbling phases.

Therefore, our click events are propagated to the parent elements unless we stop them from doing so explicitly.

So if we have:

<root>
  <div onClick={this.handleAllClickEvents}>
    <foo>
      <bar>
        <target />
      </bar>
    </foo>
  </div>
</root>

We can listen to click events from child component with the handleAllClickEvents method.

Within it, we can write:

handleAllClickEvents(event) {
  const target = event.relatedTarget;
  const targetId = target.id;
  switch(targetId) {
    case 'foo':
      //...
    case 'bar':
      //...
  }
}

We get the click target with the event.relatedTarget property.

Then we get the click target’s ID with the id property.

Then we can check the IDs as we wish.

Difference Ways to Set the Initial State in a React Class Component

There’re multiple ways to set the initial state of a component in a class.

One way is standard and the other isn’t.

The standard way would be:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'james'
    }
  }

  render() {
    return  <div>{this.state.name}</div>
  }
}

We set it in the constructor with the this.state assignment.

The non-standard way is:

class App extends Component {
  state = {
    name: 'John'
  }

  render() {
    return  <div>{this.state.name}</div>
  }
}

This isn’t standard JavaScript syntax.

However, we can use it with TypeScript or a Babel plugin to transform it back to standard JavaScript.

This also sets the this.state instance variable.

Pass Props to a Component Passed as a Prop

If we want to pass props to a component that has been passed in as a prop, then we need to clone with the React.cloneElement method.

For instance, we can write:

const GrandChild = props => <div>{props.count}</div>;

class Child extends React.Component{
  constructor(){
    super();
    this.state = { count: 1 };
    this.updateCount= this.updateCount.bind(this);
  }

  updateCount(){
    this.setState(prevState => ({ count: prevState.count + 1 }))
  }

  render(){
    const Comp = this.props.comp;
    return (
      <div>
        {React.cloneElement(Comp, { count: this.state.count })}
        <button onClick={this.updateCount}>+</button>
      </div>
    );
  }
}

class Parent extends React.Component{
  render() {
    return(
      <Child comp={<GrandChild />} />
    )
  }
}

We have the GrandChild component which displays the count prop.

Then we have the Child prop to let us update the count state.

We pass that into the component that’s been passed in from the comp prop with React.cloneElement .

We got to clone it so that we return a version of the component that’s writable.

The 2nd argument has the prop name and value that we want to pass in respectively.

Conclusion

We can pass in props to a component that’s been passed in as a prop with the cloneElement method.

With portals, we can render our component anywhere we like.

And we can disable React Router links with CSS.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *